import os
# 在程序开头添加以下代码来抑制警告
os.environ['TK_SILENCE_DEPRECATION'] = '1'
import tkinter as tk
from tkinter import ttk, messagebox, simpledialog
import os


class StudentGradeManager:
    def __init__(self):
        # 初始化主窗口
        self.root = tk.Tk()
        self.root.title("学生成绩管理系统")
        self.root.geometry("800x600") # 设置窗口初始大小
        self.root.resizable(True, True) #允许用户调整窗口大小

        # 初始化学生列表
        self.students = []

        # 尝试从文件加载数据
        self.load_data()

        # 创建GUI界面
        self.create_gui()

    def load_data(self):
        """从文件加载学生数据"""
        try:
            if os.path.exists('grades.txt'):
                with open('grades.txt', 'r', encoding='utf-8') as f:
                    for line in f:
                        data = line.strip().split(',')
                        if len(data) == 5:
                            student = {
                                '学号': data[0],
                                '姓名': data[1],
                                '语文': float(data[2]),
                                '数学': float(data[3]),
                                '英语': float(data[4])
                            }
                            self.students.append(student)
                print("数据加载成功！")
            else:
                print("未找到数据文件，将创建新文件。")
        except Exception as e:
            print(f"加载数据时出错: {e}")

    def save_data(self):
        """保存学生数据到文件"""
        try:
            with open('grades.txt', 'w', encoding='utf-8') as f:
                for student in self.students:
                    # 使用格式化字符串保留一位小数
                    line = f"{student['学号']},{student['姓名']},{student['语文']:.1f},{student['数学']:.1f},{student['英语']:.1f}\n"
                    f.write(line)
            print("数据保存成功！")
        except Exception as e:
            print(f"保存数据时出错: {e}")

    def validate_grade(self, grade_str):
        """验证成绩输入是否有效（支持整数和小数）"""
        try:
            grade = float(grade_str)
            if 0 <= grade <= 100:
                return True, grade
            else:
                return False, "成绩必须在0-100之间！"
        except ValueError:
            return False, "成绩必须是数字！"

    def create_gui(self):
        """创建图形用户界面"""
        # 创建主框架
        main_frame = ttk.Frame(self.root, padding="10")
        main_frame.grid(row=0, column=0, sticky=(tk.W, tk.E, tk.N, tk.S))

        # 配置网格权重，使界面可以自适应大小
        self.root.columnconfigure(0, weight=1)
        self.root.rowconfigure(0, weight=1)
        main_frame.columnconfigure(1, weight=1)
        main_frame.rowconfigure(1, weight=1)

        # 标题标签
        title_label = ttk.Label(main_frame, text="学生成绩管理系统",
                                font=("Arial", 16, "bold"))
        title_label.grid(row=0, column=0, columnspan=2, pady=(0, 20))

        # 按钮框架
        button_frame = ttk.Frame(main_frame)
        button_frame.grid(row=1, column=0, sticky=(tk.N, tk.S), padx=(0, 10))

        # 功能按钮
        buttons = [
            ("添加学生成绩", self.add_student),
            ("查看所有成绩", self.view_all_grades),
            ("删除学生成绩", self.delete_student),
            ("修改学生成绩", self.modify_student),
            ("查找学生成绩", self.search_student),
            ("成绩统计分析", self.analyze_grades),
            ("绘制统计图表", self.draw_statistics_chart),
            ("退出系统", self.exit_system)
        ]

        for i, (text, command) in enumerate(buttons):
            button = ttk.Button(button_frame, text=text, command=command, width=15)
            button.grid(row=i, column=0, pady=5, sticky=(tk.W, tk.E))

        # 内容显示区域 - 使用PanedWindow实现可调整分割
        content_paned = ttk.PanedWindow(main_frame, orient=tk.VERTICAL)
        content_paned.grid(row=1, column=1, sticky=(tk.W, tk.E, tk.N, tk.S))

        # 文本显示框架
        text_frame = ttk.Frame(content_paned)
        content_paned.add(text_frame, weight=1)

        # 图表显示框架
        chart_frame = ttk.Frame(content_paned)
        content_paned.add(chart_frame, weight=1)

        # 结果显示区域
        self.result_text = tk.Text(text_frame, height=15, width=60, wrap=tk.NONE)
        scrollbar_y = ttk.Scrollbar(text_frame, orient=tk.VERTICAL, command=self.result_text.yview)
        scrollbar_x = ttk.Scrollbar(text_frame, orient=tk.HORIZONTAL, command=self.result_text.xview)
        self.result_text.configure(yscrollcommand=scrollbar_y.set, xscrollcommand=scrollbar_x.set)

        self.result_text.grid(row=0, column=0, sticky=(tk.W, tk.E, tk.N, tk.S))
        scrollbar_y.grid(row=0, column=1, sticky=(tk.N, tk.S))
        scrollbar_x.grid(row=1, column=0, sticky=(tk.W, tk.E))

        text_frame.columnconfigure(0, weight=1)
        text_frame.rowconfigure(0, weight=1)

        # 图表显示区域 - 增加高度
        self.chart_canvas = tk.Canvas(chart_frame, width=500, height=350, bg="white")  # 增加高度到350
        self.chart_canvas.grid(row=0, column=0, sticky=(tk.W, tk.E, tk.N, tk.S))

        chart_frame.columnconfigure(0, weight=1)
        chart_frame.rowconfigure(0, weight=1)

        # 初始显示欢迎信息
        self.show_welcome_message()

    def show_welcome_message(self):
        """显示欢迎信息"""
        welcome_text = "欢迎使用学生成绩管理系统！\n\n"
        welcome_text += "请使用左侧按钮进行操作：\n"
        welcome_text += "• 添加学生成绩：录入新的学生成绩信息\n"
        welcome_text += "• 查看所有成绩：显示所有学生的成绩信息\n"
        welcome_text += "• 删除学生成绩：根据学号删除学生信息\n"
        welcome_text += "• 修改学生成绩：根据学号修改学生信息\n"
        welcome_text += "• 查找学生成绩：根据学号查找学生信息\n"
        welcome_text += "• 成绩统计分析：显示各科成绩统计信息\n"
        welcome_text += "• 绘制统计图表：绘制各科平均分柱状图\n"
        welcome_text += "• 退出系统：保存数据并退出程序\n\n"
        welcome_text += f"当前系统中共有 {len(self.students)} 名学生记录。"

        self.display_text(welcome_text)

    def display_text(self, text):
        """在结果显示区域显示文本"""
        self.result_text.delete(1.0, tk.END)
        self.result_text.insert(1.0, text)

    def add_student(self):
        """添加学生成绩"""
        # 创建添加学生窗口
        add_window = tk.Toplevel(self.root)
        add_window.title("添加学生成绩")
        add_window.geometry("400x320")  # 稍微增加高度以容纳提示信息
        add_window.transient(self.root)
        add_window.grab_set()

        # 提示信息
        ttk.Label(add_window, text="注意：成绩支持小数输入",
                 font=("Arial", 9), foreground="blue").grid(row=0, column=0, columnspan=2, pady=5)

        # 学号输入框
        ttk.Label(add_window, text="学号:").grid(row=1, column=0, padx=10, pady=10, sticky=tk.W)
        id_entry = ttk.Entry(add_window, width=20)
        id_entry.grid(row=1, column=1, padx=10, pady=10, sticky=(tk.W, tk.E))

        # 姓名输入框
        ttk.Label(add_window, text="姓名:").grid(row=2, column=0, padx=10, pady=10, sticky=tk.W)
        name_entry = ttk.Entry(add_window, width=20)
        name_entry.grid(row=2, column=1, padx=10, pady=10, sticky=(tk.W, tk.E))

        # 语文成绩输入框
        ttk.Label(add_window, text="语文成绩:").grid(row=3, column=0, padx=10, pady=10, sticky=tk.W)
        chinese_entry = ttk.Entry(add_window, width=20)
        chinese_entry.grid(row=3, column=1, padx=10, pady=10, sticky=(tk.W, tk.E))

        # 数学成绩输入框
        ttk.Label(add_window, text="数学成绩:").grid(row=4, column=0, padx=10, pady=10, sticky=tk.W)
        math_entry = ttk.Entry(add_window, width=20)
        math_entry.grid(row=4, column=1, padx=10, pady=10, sticky=(tk.W, tk.E))

        # 英语成绩输入框
        ttk.Label(add_window, text="英语成绩:").grid(row=5, column=0, padx=10, pady=10, sticky=tk.W)
        english_entry = ttk.Entry(add_window, width=20)
        english_entry.grid(row=5, column=1, padx=10, pady=10, sticky=(tk.W, tk.E))

        def submit():
            """提交学生信息"""
            # 获取输入值
            student_id = id_entry.get().strip()
            name = name_entry.get().strip()
            chinese = chinese_entry.get().strip()
            math = math_entry.get().strip()
            english = english_entry.get().strip()

            # 验证输入
            if not student_id or not name or not chinese or not math or not english:
                messagebox.showerror("输入错误", "所有字段都必须填写！")
                return

            # 检查学号是否重复
            for student in self.students:
                if student['学号'] == student_id:
                    messagebox.showerror("输入错误", "该学号已存在，请使用不同的学号！")
                    return

            # 验证成绩是否为有效数字
            chinese_valid, chinese_result = self.validate_grade(chinese)
            if not chinese_valid:
                messagebox.showerror("输入错误", f"语文成绩{chinese_result}")
                return

            math_valid, math_result = self.validate_grade(math)
            if not math_valid:
                messagebox.showerror("输入错误", f"数学成绩{math_result}")
                return

            english_valid, english_result = self.validate_grade(english)
            if not english_valid:
                messagebox.showerror("输入错误", f"英语成绩{english_result}")
                return

            # 添加学生
            new_student = {
                '学号': student_id,
                '姓名': name,
                '语文': chinese_result,
                '数学': math_result,
                '英语': english_result
            }
            self.students.append(new_student)

            messagebox.showinfo("成功", "学生成绩添加成功！")
            add_window.destroy()
            self.show_welcome_message()

        # 提交按钮
        submit_button = ttk.Button(add_window, text="提交", command=submit)
        submit_button.grid(row=6, column=0, columnspan=2, pady=20)

        # 配置网格权重
        add_window.columnconfigure(1, weight=1)

    def view_all_grades(self):
        """查看所有成绩"""
        if not self.students:
            self.display_text("系统中暂无学生信息！")
            return

        # 构建表格文本
        table_text = "学号\t姓名\t语文\t数学\t英语\t总分\t平均分\n"
        table_text += "-" * 70 + "\n"

        for student in self.students:
            total = student['语文'] + student['数学'] + student['英语']
            average = total / 3
            table_text += f"{student['学号']}\t{student['姓名']}\t{student['语文']:.1f}\t{student['数学']:.1f}\t{student['英语']:.1f}\t{total:.1f}\t{average:.1f}\n"

        self.display_text(table_text)

    def delete_student(self):
        """删除学生成绩"""
        if not self.students:
            messagebox.showinfo("提示", "系统中暂无学生信息！")
            return

        # 获取要删除的学生学号
        student_id = simpledialog.askstring("删除学生", "请输入要删除的学生学号:")
        if not student_id:
            return

        # 查找并删除学生
        found = False
        for i, student in enumerate(self.students):
            if student['学号'] == student_id:
                del self.students[i]
                found = True
                break

        if found:
            messagebox.showinfo("成功", "学生信息删除成功！")
            self.show_welcome_message()
        else:
            messagebox.showerror("错误", "未找到该学号的学生！")

    def modify_student(self):
        """修改学生成绩"""
        if not self.students:
            messagebox.showinfo("提示", "系统中暂无学生信息！")
            return

        # 获取要修改的学生学号
        student_id = simpledialog.askstring("修改学生", "请输入要修改的学生学号:")
        if not student_id:
            return

        # 查找学生
        student_to_modify = None
        for student in self.students:
            if student['学号'] == student_id:
                student_to_modify = student
                break

        if not student_to_modify:
            messagebox.showerror("错误", "未找到该学号的学生！")
            return

        # 创建修改窗口
        modify_window = tk.Toplevel(self.root)
        modify_window.title("修改学生成绩")
        modify_window.geometry("400x370")  # 增加高度
        modify_window.transient(self.root)
        modify_window.grab_set()

        # 提示信息
        ttk.Label(modify_window, text="注意：成绩支持小数输入",
                 font=("Arial", 9), foreground="blue").grid(row=0, column=0, columnspan=2, pady=5)

        # 显示当前信息
        ttk.Label(modify_window, text=f"当前学生信息 - 学号: {student_to_modify['学号']}",
                  font=("Arial", 10, "bold")).grid(row=1, column=0, columnspan=2, pady=10)

        # 姓名输入框
        ttk.Label(modify_window, text="姓名:").grid(row=2, column=0, padx=10, pady=10, sticky=tk.W)
        name_entry = ttk.Entry(modify_window, width=20)
        name_entry.insert(0, student_to_modify['姓名'])
        name_entry.grid(row=2, column=1, padx=10, pady=10, sticky=(tk.W, tk.E))

        # 语文成绩输入框
        ttk.Label(modify_window, text="语文成绩:").grid(row=3, column=0, padx=10, pady=10, sticky=tk.W)
        chinese_entry = ttk.Entry(modify_window, width=20)
        chinese_entry.insert(0, f"{student_to_modify['语文']:.1f}")  # 格式化显示
        chinese_entry.grid(row=3, column=1, padx=10, pady=10, sticky=(tk.W, tk.E))

        # 数学成绩输入框
        ttk.Label(modify_window, text="数学成绩:").grid(row=4, column=0, padx=10, pady=10, sticky=tk.W)
        math_entry = ttk.Entry(modify_window, width=20)
        math_entry.insert(0, f"{student_to_modify['数学']:.1f}")  # 格式化显示
        math_entry.grid(row=4, column=1, padx=10, pady=10, sticky=(tk.W, tk.E))

        # 英语成绩输入框
        ttk.Label(modify_window, text="英语成绩:").grid(row=5, column=0, padx=10, pady=10, sticky=tk.W)
        english_entry = ttk.Entry(modify_window, width=20)
        english_entry.insert(0, f"{student_to_modify['英语']:.1f}")  # 格式化显示
        english_entry.grid(row=5, column=1, padx=10, pady=10, sticky=(tk.W, tk.E))

        def submit_modification():
            """提交修改"""
            # 获取输入值
            name = name_entry.get().strip()
            chinese = chinese_entry.get().strip()
            math = math_entry.get().strip()
            english = english_entry.get().strip()

            # 验证输入
            if not name or not chinese or not math or not english:
                messagebox.showerror("输入错误", "所有字段都必须填写！")
                return

            # 验证成绩是否为有效数字
            chinese_valid, chinese_result = self.validate_grade(chinese)
            if not chinese_valid:
                messagebox.showerror("输入错误", f"语文成绩{chinese_result}")
                return

            math_valid, math_result = self.validate_grade(math)
            if not math_valid:
                messagebox.showerror("输入错误", f"数学成绩{math_result}")
                return

            english_valid, english_result = self.validate_grade(english)
            if not english_valid:
                messagebox.showerror("输入错误", f"英语成绩{english_result}")
                return

            # 更新学生信息
            student_to_modify['姓名'] = name
            student_to_modify['语文'] = chinese_result
            student_to_modify['数学'] = math_result
            student_to_modify['英语'] = english_result

            messagebox.showinfo("成功", "学生信息修改成功！")
            modify_window.destroy()
            self.show_welcome_message()

        # 提交按钮
        submit_button = ttk.Button(modify_window, text="提交修改", command=submit_modification)
        submit_button.grid(row=6, column=0, columnspan=2, pady=20)

        # 配置网格权重
        modify_window.columnconfigure(1, weight=1)

    def search_student(self):
        """查找学生成绩"""
        if not self.students:
            messagebox.showinfo("提示", "系统中暂无学生信息！")
            return

        # 获取要查找的学生学号
        student_id = simpledialog.askstring("查找学生", "请输入要查找的学生学号:")
        if not student_id:
            return

        # 查找学生
        found_student = None
        for student in self.students:
            if student['学号'] == student_id:
                found_student = student
                break

        if not found_student:
            messagebox.showerror("错误", "未找到该学号的学生！")
            return

        # 显示学生信息
        total = found_student['语文'] + found_student['数学'] + found_student['英语']
        average = total / 3

        info_text = f"学号：{found_student['学号']}\n"
        info_text += f"姓名：{found_student['姓名']}\n"
        info_text += f"语文：{found_student['语文']:.1f}\n"  # 格式化显示
        info_text += f"数学：{found_student['数学']:.1f}\n"  # 格式化显示
        info_text += f"英语：{found_student['英语']:.1f}\n"  # 格式化显示
        info_text += f"总分：{total:.1f}\n"
        info_text += f"平均分：{average:.1f}"

        self.display_text(info_text)

    def analyze_grades(self):
        """成绩统计分析"""
        if not self.students:
            self.display_text("系统中暂无学生信息！")
            return

        # 收集各科成绩
        chinese_scores = []
        math_scores = []
        english_scores = []

        for student in self.students:
            chinese_scores.append(student['语文'])
            math_scores.append(student['数学'])
            english_scores.append(student['英语'])

        # 计算统计信息
        chinese_avg = sum(chinese_scores) / len(chinese_scores)
        chinese_max = max(chinese_scores)
        chinese_min = min(chinese_scores)

        math_avg = sum(math_scores) / len(math_scores)
        math_max = max(math_scores)
        math_min = min(math_scores)

        english_avg = sum(english_scores) / len(english_scores)
        english_max = max(english_scores)
        english_min = min(english_scores)

        # 显示统计信息
        analysis_text = "--- 成绩统计分析 ---\n\n"
        analysis_text += f"语文 - 平均分：{chinese_avg:.1f}，最高分：{chinese_max:.1f}，最低分：{chinese_min:.1f}\n"
        analysis_text += f"数学 - 平均分：{math_avg:.1f}，最高分：{math_max:.1f}，最低分：{math_min:.1f}\n"
        analysis_text += f"英语 - 平均分：{english_avg:.1f}，最高分：{english_max:.1f}，最低分：{english_min:.1f}"

        self.display_text(analysis_text)

    def draw_statistics_chart(self):
        """绘制简单的统计图表（各科平均分柱状图）"""
        if not self.students:
            messagebox.showinfo("提示", "系统中暂无学生信息！")
            return

        # 收集各科成绩
        chinese_scores = []
        math_scores = []
        english_scores = []

        for student in self.students:
            chinese_scores.append(student['语文'])
            math_scores.append(student['数学'])
            english_scores.append(student['英语'])

        # 计算平均分
        chinese_avg = sum(chinese_scores) / len(chinese_scores)
        math_avg = sum(math_scores) / len(math_scores)
        english_avg = sum(english_scores) / len(english_scores)

        # 清除画布
        self.chart_canvas.delete("all")

        # 获取画布实际尺寸
        canvas_width = self.chart_canvas.winfo_width()
        canvas_height = self.chart_canvas.winfo_height()

        # 如果画布还没有被渲染，使用默认尺寸
        if canvas_width < 10:
            canvas_width = 500
        if canvas_height < 10:
            canvas_height = 350

        # 设置图表边距 - 根据实际尺寸调整
        margin_top = 40
        margin_bottom = 50  # 为横坐标标签留出足够空间
        margin_left = 60
        margin_right = 30

        chart_width = canvas_width - margin_left - margin_right
        chart_height = canvas_height - margin_top - margin_bottom

        # 如果计算出的图表区域太小，使用最小保证值
        if chart_width < 200:
            chart_width = 200
            canvas_width = chart_width + margin_left + margin_right
        if chart_height < 150:
            chart_height = 150
            canvas_height = chart_height + margin_top + margin_bottom

        # 柱子参数
        bar_width = min(50, chart_width // 6)  # 动态调整柱子宽度
        bar_spacing = min(30, chart_width // 8)

        # 计算比例因子
        max_avg = max(chinese_avg, math_avg, english_avg)
        scale_max = max(100, max_avg * 1.2)  # 留出20%的顶部空间
        scale_factor = chart_height / scale_max

        # 绘制坐标轴
        # Y轴
        self.chart_canvas.create_line(margin_left, margin_top,
                                      margin_left, canvas_height - margin_bottom,
                                      width=2)
        # X轴
        self.chart_canvas.create_line(margin_left, canvas_height - margin_bottom,
                                      canvas_width - margin_right, canvas_height - margin_bottom,
                                      width=2)

        # 绘制Y轴刻度和标签
        for i in range(0, int(scale_max) + 1, 20):
            y = canvas_height - margin_bottom - i * scale_factor
            # 刻度线
            self.chart_canvas.create_line(margin_left - 5, y, margin_left, y, width=1)
            # 刻度标签
            self.chart_canvas.create_text(margin_left - 8, y, text=str(i),
                                          anchor=tk.E, font=("Arial", 8))

        # 绘制柱状图
        subjects = ["语文", "数学", "英语"]
        averages = [chinese_avg, math_avg, english_avg]
        colors = ["#FF6B6B", "#4ECDC4", "#45B7D1"]

        for i, (subject, avg, color) in enumerate(zip(subjects, averages, colors)):
            # 计算柱子位置 - 居中分布
            total_bars_width = len(subjects) * bar_width + (len(subjects) - 1) * bar_spacing
            start_x = margin_left + (chart_width - total_bars_width) / 2
            x = start_x + i * (bar_width + bar_spacing)

            bar_height = avg * scale_factor

            # 绘制柱子
            self.chart_canvas.create_rectangle(
                x, canvas_height - margin_bottom - bar_height,
                   x + bar_width, canvas_height - margin_bottom,
                fill=color, outline="black", width=1
            )

            # 添加数值标签（在柱子顶部）
            self.chart_canvas.create_text(
                x + bar_width / 2, canvas_height - margin_bottom - bar_height - 12,
                text=f"{avg:.1f}", font=("Arial", 9, "bold")
            )

            # 添加科目标签（在X轴下方）
            label_y = canvas_height - margin_bottom + 20
            self.chart_canvas.create_text(
                x + bar_width / 2, label_y,
                text=subject, font=("Arial", 10, "bold")
            )

        # 添加图表标题
        self.chart_canvas.create_text(
            canvas_width // 2, 15,
            text="各科平均分统计图", font=("Arial", 12, "bold")
        )

        # 添加Y轴标签
        self.chart_canvas.create_text(
            15, canvas_height // 2,
            text="分数", angle=90, font=("Arial", 10)
        )

        # 显示统计信息
        stats_text = "--- 各科平均分统计 ---\n\n"
        stats_text += f"语文: {chinese_avg:.1f}分\n"
        stats_text += f"数学: {math_avg:.1f}分\n"
        stats_text += f"英语: {english_avg:.1f}分\n\n"
        stats_text += f"最高平均分: {max_avg:.1f}分"

        self.display_text(stats_text)

    def exit_system(self):
        """退出系统"""
        # 保存数据
        self.save_data()

        # 显示退出信息
        messagebox.showinfo("感谢使用", "数据已保存！感谢使用学生成绩管理系统！")

        # 退出程序
        self.root.quit()

    def run(self):
        """运行应用程序"""
        self.root.mainloop()


# 程序入口
if __name__ == "__main__":
    # 创建并运行学生成绩管理系统
    app = StudentGradeManager()
    app.run()